<?php

class DynamicParticipantForm extends sfForm
{
  
  /**
   * @var Doctrine_Collection
   */
  private $participants;
  
  const MIN_NUM_FORMS = 5;
  const OPTION_PARTICIPANT_DEFAULT_VALUES = 'participant_default_values';
  const OPTION_LOGGER = 'logger';

  public function __construct (Doctrine_Collection $coll, $options = array())
  {
    if ($coll->getTable()
      ->getTableName() !== ParticipantTable::getInstance()->getTableName())
    {
      throw new InvalidArgumentException();
    }
    
    $this->participants = $coll;
    parent::__construct(array(), $options);
    
    $this->getLogger()->debug(sprintf('Constructed new %s', __CLASS__));

  }

  public function configure ()
  {
    $num_existent_participants = count($this->participants);
    $this->getLogger()->debug(sprintf('Number of existent participants: %s', $num_existent_participants));
    
    if ($num_existent_participants > 0)
    {
      foreach ($this->participants as $participant)
      {
        $this->addForm($participant);
      }
    }
    
//    if ($num_existent_participants < self::MIN_NUM_FORMS)
//    {
      $num_blank_participants = self::MIN_NUM_FORMS - $num_existent_participants;
      if($num_blank_participants <= 0) {
        $num_blank_participants = 1;
      }
      $this->getLogger()->debug(sprintf('Number of blank participants: %s', $num_blank_participants));
      for ($i = 0; $i < $num_blank_participants; $i ++)
      {
        $this->addForm();
      }
//    }
    
    $this->widgetSchema->setNameFormat('dynamic_participants[%s]');
    
    $this->getLogger()->debug(sprintf('Merging post validators'));
    $post_validator = new EmbeddedParticipantValidatorSchema();
    $post_validator->setOption(EmbeddedParticipantValidatorSchema::OPTION_ALLOW_EMPTY, true);
    $post_validator->setOption(EmbeddedParticipantValidatorSchema::OPTION_LOGGER, $this->getLogger());
    $this->mergePostValidator($post_validator);
  }

  public function addForm (Participant $participant = null, $num = null)
  {
    $this->getLogger()->debug(sprintf('Calling %s', __METHOD__));
    if (is_null($num))
    {
      $num = $this->getNumEmbeddedForms();
    }
    $this->getLogger()->debug(sprintf('Calling %s for participant %s with index %s', __METHOD__, ($participant == null ? 'NULL' : $participant->__toString()), $num));
    
    if(is_null($participant)) {
      $participant = new Participant();
      $participant->setArray($this->getOption(self::OPTION_PARTICIPANT_DEFAULT_VALUES, array()));
      $this->getLogger()->debug(sprintf('Set default values for blank participant'));
    }
    $defaults = $this->getOption(self::OPTION_PARTICIPANT_DEFAULT_VALUES, array());
    foreach($defaults as $field => $default) {
      if(!$participant->get($field)) {
        $participant->set($field, $default);
      }
    }
    $this->getLogger()->debug(sprintf('Embedding new EmbeddedParticipantForm for participant %s', $num));
    $form = new EmbeddedParticipantForm($participant);
    $form->getWidgetSchema()
      ->setNameFormat('dynamic_participants[' . $num . '][%s]');
    $this->embedForm($num, $form);
  }

  public function getNumEmbeddedForms ()
  {
    return count($this->embeddedForms);
  }
  
  /**
   * @return array
   */
  public function getParticipantForms() {
    $num_embedded_forms = $this->getNumEmbeddedForms();
    $forms = array();
    for($i = 0; $i < $num_embedded_forms; $i++) {
      $forms[] = $this[$i];
    }
    return $forms;
  }
  
  /**
   * @param integer $i
   * @return boolean
   */
  public function hasEmbeddedForm($i) {
    return isset($this[$i]);
  }
  
  public function bind(array $taintedValues = null, array $taintedFiles = null) {
    $this->getLogger()->debug(sprintf('Calling %s', __METHOD__));
    foreach($taintedValues as $i => $value) {
      if(is_numeric($i) && !$this->hasEmbeddedForm($i)) {
        $this->addForm();
      }
    }
    
    return parent::bind($taintedValues, $taintedFiles);
  }
  
  public function getParticipants() {
    // TODO implement
    $this->getLogger()->debug(sprintf('Calling %s', __METHOD__));
    $participants = new Doctrine_Collection('Participant');
    $values = $this->getValues();
    $this->getLogger()->debug(sprintf('Found %s values with getValues()', count($values)));
    $this->getLogger()->debug(sprintf('Found %s embedded forms', count($this->getEmbeddedForms())));
    //array_pop($values); // Dirty fix? But it works :)
    foreach($this->getEmbeddedForms() as $i => $form) {
      if($form instanceof EmbeddedParticipantForm && isset($values[$i])) {
        $id = $values[$i]['id'];
        $this->getLogger()->debug(sprintf('Found EmbeddedParticipantForm instance for index %s, creating participant from values:<br /> %s', $i, print_r($values[$i], true)));
        $this->getLogger()->debug(sprintf('Loggind participant\'s id only from values array: %s', $id));
        //$this->getLogger()->debug(sprintf('Is EmbeddedParticipantForm valid: %s', ($form->isValid() ? 'TRUE' : 'FALSE')));
        //$participant = new Participant();
        if($id > 0) {
          $participant = ParticipantTable::getInstance()->findOneById($id);
        } else {
          $participant = new Participant();
        }
        //$participant->setId($id);
        $participant->setArray($values[$i]);
        $participants->add($participant);
        $this->getLogger()->debug(sprintf('Participant object values after setting: %s', print_r($participant->toArray(false), true)));
      }
    }
    return $participants;
  }  
  
  public function addPreviouslyAddedForms(array $taintedValues = null) {
    $this->getLogger()->debug(sprintf('Calling %s', __METHOD__));
    foreach ( $taintedValues as $key => $address ) {
      if (is_numeric($key) && ! isset ( $this[$key] )) {
        $this->addForm(null, $key);
      }
    }
  }
  
  /**
   * @return sfLogger
   */
  public function getLogger() {
    return $this->getOption(self::OPTION_LOGGER);
  }
}